/*********************************************************************\
*                                                                     *
*         Jamper - Java XML mapper (visual XSLT generator)            *
*                Copyright (C) 2005 Filip Pavlovic                    *
*                    sqba@users.sourceforge.net                       *
*                                                                     *
*  This program is free software; you can redistribute it and/or      *
*  modify it under the terms of the GNU General Public License        *
*  as published by the Free Software Foundation; either version 2     *
*  of the License, or (at your option) any later version.             *
*                                                                     *
*  This program is distributed in the hope that it will be useful,    *
*  but WITHOUT ANY WARRANTY; without even the implied warranty of     *
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the      *
*  GNU General Public License for more details.                       *
*                                                                     *
*  You should have received a copy of the GNU General Public License  *
*  along with this program; if not, write to the Free Software        *
*  Foundation, Inc., 59 Temple Place - Suite 330, Boston,             *
*  MA 02111-1307, USA.                                                *
*                                                                     *
\*********************************************************************/


package sqba.jamper;


import sqba.jamper.map.IPropObject;
import sqba.jamper.map.ObjectProperty;
import sqba.jamper.map.object.FunctionBox;
import sqba.jamper.map.object.IMapObject;
import sqba.jamper.map.object.LinkLine;
import sqba.jamper.map.object.VariableBox;
import sqba.jamper.map.tree.MapperTree;
import sqba.jamper.map.tree.MapperTreeNode;

import java.awt.Dimension;
import java.awt.ComponentOrientation;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;

import javax.swing.JTable;
import javax.swing.JSplitPane;
import javax.swing.JComponent;
import javax.swing.JScrollPane;
import javax.swing.tree.TreePath;
import javax.swing.table.AbstractTableModel;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;


/**
 * Table view that shows object properties.
 *
 * @author	Filip Pavlovic
 * @version	1.0
 */
public class PropertyPane extends JSplitPane implements TreeSelectionListener
{
	private MyTableModel _leftTableModel, _rightTableModel;

	/**
	 * Constructor
	 * initializes the pane.
	 *
	 * @param mapper XMLMapper
	 */
	public PropertyPane(JComponent parent)
	{
        _leftTableModel  = new MyTableModel();
        _rightTableModel = new MyTableModel();

		JTable leftTable  = new JTable(_leftTableModel);
		JTable rightTable = new JTable(_rightTableModel);

		Dimension d = parent.getSize(null);
		leftTable.setPreferredScrollableViewportSize(d);
		rightTable.setPreferredScrollableViewportSize(d);

		JScrollPane leftPane  = new JScrollPane(leftTable);
		JScrollPane rightPane = new JScrollPane(rightTable);

		leftPane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
		rightPane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);

		leftPane.setWheelScrollingEnabled(true);
		rightPane.setWheelScrollingEnabled(true);

		this.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
		this.setLeftComponent(leftPane);
		this.setRightComponent(rightPane);
		this.setDividerLocation(d.width/2);
        this.setContinuousLayout(true);

		setPreferredSize(d);

		this.addComponentListener(new MyComponentListener());
	}

    class MyTableModel extends AbstractTableModel
    {
		private final String[] _columnNames = {"Property", "Value"};
		private IPropObject _obj = null;

		private void setPropObject(IPropObject obj)
		{
			_obj = obj;
			fireTableDataChanged();
		}

		public int		getColumnCount()		{ return _columnNames.length; }
		public String	getColumnName(int col)	{ return _columnNames[col]; }

        public int getRowCount()
    		{ return (_obj!=null ? _obj.getPropertyCount() : 0); }

        public Object getValueAt(int row, int col)
        {
        	if(_obj != null) {
        		ObjectProperty prop = _obj.getProperty(row);
	        	switch(col)
	        	{
	        		case 0:
	        			return prop.getName();
	         		case 1:
	         			return prop.getValue();
		        	default:
		        		return null;
		        }
       		} else
        		return null;
        }

        /*
         * JTable uses this method to determine the default renderer/
         * editor for each cell.  If we didn't implement this method,
         * then the last column would contain text ("true"/"false"),
         * rather than a check box.
         */
        public Class getColumnClass(int c)
        {
            return getValueAt(0, c).getClass();
        }

        /*
         * Don't need to implement this method unless your table's
         * editable.
         */
        public boolean isCellEditable(int row, int col)
        {
			//Note that the data/cell address is constant,
			//no matter where the cell appears onscreen.
			//return false;
			return (1 == col);
        }

        /*
         * Don't need to implement this method unless your table's
         * data can change.
         */
        public void setValueAt(Object value, int row, int col)
        {
			/*if (data[0][col] instanceof Integer
				&& !(value instanceof Integer)) {
				//With JFC/Swing 1.1 and JDK 1.2, we need to create
				//an Integer from the value; otherwise, the column
				//switches to contain Strings.  Starting with v 1.3,
				//the table automatically converts value to an Integer,
				//so you only need the code in the 'else' part of this
				//'if' block.
				//XXX: See TableEditDemo.java for a better solution!!!
				try {
					data[row][col] = new Integer(value.toString());
					fireTableCellUpdated(row, col);
				} catch (NumberFormatException e) {
					System.out.println("The \"" + getColumnName(col)
					+ "\" column accepts only integer values.");
				}
			} else {
				data[row][col] = value;
				fireTableCellUpdated(row, col);
			}*/
			//System.out.println("value=" + value + " row=" + row + " col=" + col);
	    	if((null != _obj) && (col == 1)) {
	    		ObjectProperty prop = _obj.getProperty(row);
	    		prop.setValue(value);
				fireTableCellUpdated(row, col);
			}
        }
	}

	class MyComponentListener implements ComponentListener
	{
		public void componentHidden(ComponentEvent e) {}
		public void componentMoved(ComponentEvent e) {}
		public void componentResized(ComponentEvent e)
		{
			PropertyPane.this.setDividerLocation(getWidth()/2);
		}
		public void componentShown(ComponentEvent e) {}
	}

	/**
	 * Called when a map object has been selected.
	 *
	 * @param obj pointer to the MapObject interface
	 * of the selected object.
	 */
	public void objectSelected(IMapObject obj)
	{
		if(obj instanceof MapperTreeNode) {
			setDividerLocation(0.5);
			MapperTreeNode node = (MapperTreeNode)obj;
			MapperTree tree = (MapperTree)node.getTree();
			if(!tree.isSinkTree())
				_leftTableModel.setPropObject(node);
			else
				_rightTableModel.setPropObject(node);
		} else if(obj instanceof FunctionBox) {
			setDividerLocation(1.0);
			_leftTableModel.setPropObject(obj);
		} else if(obj instanceof VariableBox) {
			_leftTableModel.setPropObject(obj);
			setDividerLocation(1.0);
		} else if(obj instanceof LinkLine) {
			_leftTableModel.setPropObject(obj);
			setDividerLocation(1.0);
		} else if(obj instanceof IPropObject) {
			_leftTableModel.setPropObject(obj);
			setDividerLocation(1.0);
		}
	}

	/////////////////////////////////////////////////////////////
	// TreeSelectionListener interface implementation
	/////////////////////////////////////////////////////////////
	public void valueChanged(TreeSelectionEvent e)
	{
		TreePath path = e.getNewLeadSelectionPath();
		if(path != null) {
			MapperTreeNode node = (MapperTreeNode)path.getLastPathComponent();
			if (node != null){
				objectSelected(node);
				/*MapperTree tree = (MapperTree)node.getTree();
				if(!tree.isSinkTree())
					_leftTableModel.setMapperTreeNode(node);
				else
					_rightTableModel.setMapperTreeNode(node);*/
			}
		}
	}
}
